package com.yhb.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.yhb.conf.ResultCode;
import com.yhb.dao.LogMapper;
import com.yhb.service.AppPayService;
import com.yhb.service.LogService;
import com.yhb.service.OrderService;
import com.yhb.utils.Constants;
import com.yhb.utils.DateUtils;
import me.edzh.spring.bootstrap.utils.security.HashUtils;
import lombok.extern.log4j.Log4j;
import me.edzh.spring.bootstrap.model.Tuple;
import me.edzh.spring.bootstrap.utils.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;
import java.util.UUID;

@Log4j
@Service
public class AliAppPayServiceImplApp implements AppPayService {

    private AlipayClient alipayClient;

    @Value("${alipay.appid}")
    private String appId;

    @Value("${alipay.privateKey}")
    private String rsaPrivateKey;

    @Value("${alipay.publicKey}")
    private String rsaPublicKey;

    @Lazy
    @Autowired
    private OrderService orderService;

    @Autowired
    private LogService logService;

    @PostConstruct
    public void onInit() {
        java.security.Security.addProvider(
                new org.bouncycastle.jce.provider.BouncyCastleProvider()
        );
        this.alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", appId, rsaPrivateKey, "json", "utf8", rsaPublicKey, "RSA2");
    }

    @Override
    public Tuple<String, String> invokePay(BigDecimal amount, String title, String desc) {
        String orderNo = HashUtils.getMD5(UUID.randomUUID().toString());

        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody(title);
        model.setSubject(desc);
        model.setOutTradeNo(orderNo);
        model.setTimeoutExpress("30m");
        model.setTotalAmount(amount.setScale(2, RoundingMode.CEILING).toString());
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(Constants.getBaseUrl() + "callback/aliPayPurchase");
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            return new Tuple<>(orderNo, response.getBody());
        } catch (AlipayApiException e) {
            log.error(e);
            throw new ServiceException(ResultCode.ERROR_TOAST_ERR, "申请支付参数失败");
        }
    }

    @Override
    public void onCallback(Map<String, String> params) {
        log.info("received alipay callback");
        checkSign(params);
        logService.insertLog(null, "ALIPAY-CALLBACK", params);
        if (!"TRADE_SUCCESS".equals(params.get("trade_status"))) {
            return;
        }
        orderService.onOrderPurchased(params.get("out_trade_no"));
    }

    private void checkSign(Map<String, String> params) {
        try {
            AlipaySignature.rsaCheckV1(params, rsaPublicKey, "utf8", "RSA2");
        } catch (Throwable t) {
            log.warn("checksign err" + params.toString());
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "alipay check sign err", t);
        }
    }
}
